package util;

import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 工具类：可以动态的生成Dao代理对象，并且可以动态的为Dao代理对象绑定数据源
 * */
public class GenerateDaoProxy {

    public static Object generate(SqlSession sqlSession, Class daoInterface) {

        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.makeClass(daoInterface + "Proxy");
        CtClass ctInterface = pool.makeInterface(daoInterface.getName());

        ctClass.addInterface(ctInterface);

        //实现接口中所有的方法
        Method[] methods = daoInterface.getDeclaredMethods();
        Arrays.stream(methods).forEach(method -> {

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("public");
            stringBuilder.append(" ");
            String returnTypeName = method.getReturnType().getName();
            stringBuilder.append(returnTypeName);
            stringBuilder.append(" ");
            stringBuilder.append(method.getName());
            stringBuilder.append("(");
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                Class<?> parameterType =parameterTypes[i];
                stringBuilder.append(parameterType);
                stringBuilder.append(" ");
                stringBuilder.append("arg" + i);
                if (i != parameterTypes.length - 1) {
                    stringBuilder.append(",");
                }
            }
            stringBuilder.append("){");


            stringBuilder.append("org.apache.ibatis.session.SqlSession sqlSession = com.powernode.bank.util.sqlSessionUtil.openSession();");
            String sqlId = daoInterface.getName() + "." + method.getName();
            Configuration configuration = sqlSession.getConfiguration();

            MappedStatement mappedStatement = configuration.getMappedStatement(sqlId);
            SqlCommandType sqlCommandTypeName = mappedStatement.getSqlCommandType();


            //   getMappedStatement(sqlId).getSqlCommandType();

            if (SqlCommandType.SELECT == (sqlCommandTypeName)) {

                stringBuilder.append("return (" + returnTypeName + ")sqlSession.selectOne(\"" + sqlId +"\", arg0);");
            } else if (SqlCommandType.UPDATE == (sqlCommandTypeName)) {
                stringBuilder.append("int count = sqlSession.update(\"" + sqlId + "\", arg0);");
                stringBuilder.append("return count;");
            }

              stringBuilder.append("}");
            System.out.println(stringBuilder);
            try {


                CtMethod ctmethod = CtMethod.make(stringBuilder.toString(), ctClass);

                ctClass.addMethod(ctmethod);

            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        });
        //创建对象
        Object o = null;
            try {
                Class<?> aClass = ctClass.toClass();
                    o=aClass.newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return o;


    }
}

